package corp.edu.amadeus.core.business.service.impl;

import java.util.Collection;
import corp.edu.amadeus.core.business.object.impl.FileBO;
import corp.edu.amadeus.core.business.service.ifc.IFileService;
import corp.edu.amadeus.core.facade.ifc.IGenericCRUDFacade;
import corp.edu.amadeus.core.facade.ifc.IGenericSearchFacade;
import corp.edu.amadeus.core.business.locator.ObjectLocator;
import corp.edu.amadeus.utils.date.DateUtils;
import corp.edu.amadeus.commons.Constants;
import java.io.File;
import org.apache.log4j.Logger;
import corp.edu.amadeus.core.business.service.ifc.IMultimediaStorageService;
import corp.edu.amadeus.utils.security.Encoder;
import corp.edu.amadeus.utils.file.FileUtils;

public class FileServiceImpl implements IFileService {

	private IGenericCRUDFacade cFac;
	private IGenericSearchFacade sFac;
	private IMultimediaStorageService mediaStService;
	private static Logger log = Logger.getLogger(FileServiceImpl.class);

	public FileServiceImpl(IGenericCRUDFacade cFac,
			IGenericSearchFacade sFac, IMultimediaStorageService stService) {
		this.cFac = cFac;
		this.sFac = sFac;
		this.mediaStService = stService;
	}

	public void addFile(File source, String originalName,
			String lang, String description) throws Exception {
		FileBO file = ObjectLocator.getFile();
		file.setDateCreated(DateUtils.getNow());
		file.setDateModified(DateUtils.getNow());
		file.setOriginalName(originalName);
		file.setStoredName("");
		file.setLang(lang);
		file.setDescription(description);
		this.cFac.persist(file);
		/**
		 * MD5 algoritm must be applied.
		 */
		String md5_name = this.encryptFilename(originalName,
				"" + file.getPersistenceId());
		file.setStoredName(md5_name);
		this.cFac.update(file);
		this.cFac.flush();
		this.mediaStService.addFile(source, file.getStoredName());
	}

	public void updateFile(File source, int fileId,
			String originalName, String lang, String description)
			throws Exception {
		FileBO file = (FileBO)this.sFac.findByKey(FileBO.class,
				"persistenceId", fileId);
		file.setDateModified(DateUtils.getNow());
		file.setOriginalName(originalName);
		/**
		 * MD5 algoritm must be applied.
		 */
		String md5_name = this.encryptFilename(originalName,
				"" + file.getPersistenceId());
		log.debug("### ##### PERSISTENCE-ID: " +
				file.getPersistenceId());
		String old_store_name = file.getStoredName();
		file.setStoredName(md5_name);
		file.setLang(lang);
		file.setDescription(description);
		this.cFac.update(file);
		this.cFac.flush();
		if(!this.mediaStService.deleteFile(old_store_name)) {
			log.info("NO se ha podido eliminar el fichero: " +
					old_store_name);
		}

		this.mediaStService.addFile(source, file.getStoredName());
	}

	public void deleteFile(int fileId)
		throws Exception {
		FileBO file = (FileBO)this.sFac.findByKey(FileBO.class,
				"persistenceId", fileId);
		String old_store_name = file.getStoredName();
		this.cFac.delete(file);
		this.cFac.flush();
		if(!this.mediaStService.deleteFile(old_store_name)) {
			log.info("NO se ha podido eliminar el fichero: " +
					old_store_name);
		}
	}

	public Collection<FileBO> getAllFiles() {
		String query = "from FileBO order by id asc";
		return this.sFac.findByQuery(query);
	}

	public FileBO getFile(int fileId)
		throws Exception {
		return (FileBO)this.sFac.findByKey(FileBO.class,
				"persistenceId", fileId);
	}

	private String encryptFilename(String filename, String seed)
		throws Exception {
		String result = "";
		String name = FileUtils.removeFileExtension(filename);
		String file_extension = FileUtils.extractFileExtension(filename);
		String encryptedName = Encoder.encrypt(name + seed,
				Constants.ENCRYPT_ALGORITHM);
		result = encryptedName + "." + file_extension;
		return result;
	}

}